package f.h.dragon.jlog;

import org.apache.log4j.Level;

/**
 * This is the central class in the jlog package. Most logging
 * operations, except configuration, are done through this class.
 * 
 * @author Wenlong Meng(wenlong.meng@gmail.com)
 * @version jlog 1.0 at 2011/10/02
 */
public class Logger {

	// local variables
	/**
	 * log4j
	 */
	private static org.apache.log4j.Logger logger;
	/**
	 * log
	 */
	private static Logger instance;

	/**
	 * Retrieve a logger named according to the value of the <code>name</code>
	 * parameter. If the named logger already exists, then the existing instance
	 * will be returned. Otherwise, a new instance is created.
	 * 
	 * <p>
	 * By default, loggers do not have a set level but inherit it from their
	 * neareast ancestor with a set level. This is one of the central features
	 * of log4j.
	 * 
	 * @param name
	 *            The name of the logger to retrieve.
	 */
	static public Logger getLogger(String name) {
		logger = org.apache.log4j.Logger.getLogger(name);
		return getInstance();
	}

	/**
	 * Shorthand for <code>getLogger(clazz.getName())</code>.
	 * 
	 * @param clazz
	 *            The name of <code>clazz</code> will be used as the name of the
	 *            logger to retrieve. See {@link #getLogger(String)} for more
	 *            detailed information.
	 */
	static public Logger getLogger(@SuppressWarnings("rawtypes") Class clazz) {
		logger = org.apache.log4j.Logger.getLogger(clazz);
		return getInstance();
	}

	/**
	 * get instance
	 * 
	 * @return
	 */
	private static Logger getInstance() {
		if (instance == null) {
			synchronized (Logger.class) {
				instance = new Logger();
			}
		}
		return instance;
	}

	/**
	 * Log a message object with the {@link Level#INFO INFO} Level.
	 * 
	 * <p>
	 * This method first checks if this category is <code>INFO</code> enabled by
	 * comparing the level of this category with {@link Level#INFO INFO} Level.
	 * If the category is <code>INFO</code> enabled, then it converts the
	 * message object passed as parameter to a string by invoking the
	 * appropriate {@link org.apache.log4j.or.ObjectRenderer}. It proceeds to
	 * call all the registered appenders in this category and also higher in the
	 * hierarchy depending on the value of the additivity flag.
	 * 
	 * <p>
	 * <b>WARNING</b> Note that passing a {@link Throwable} to this method will
	 * print the name of the Throwable but no stack trace. To print a stack
	 * trace use the {@link #info(Object, Throwable)} form instead.
	 * 
	 * @param message
	 *            the message object to log
	 */
	public void info(Object msg) {
		if (logger.isInfoEnabled()) {
			logger.info(msg);
		}
	}

	/**
	 * Log a message object with the <code>INFO</code> level including the stack
	 * trace of the {@link Throwable} <code>t</code> passed as parameter.
	 * 
	 * <p>
	 * See {@link #info(Object)} for more detailed information.
	 * 
	 * @param message
	 *            the message object to log.
	 * @param t
	 *            the exception to log, including its stack trace.
	 */
	public void info(Object message, Throwable t) {
		if (logger.isInfoEnabled()) {
			logger.info(message, t);
		}
	}

	/**
	 * Log a message object with the {@link Level#ERROR ERROR} Level.
	 * 
	 * <p>
	 * This method first checks if this category is <code>ERROR</code> enabled
	 * by comparing the level of this category with {@link Level#ERROR ERROR}
	 * Level. If this category is <code>ERROR</code> enabled, then it converts
	 * the message object passed as parameter to a string by invoking the
	 * appropriate {@link org.apache.log4j.or.ObjectRenderer}. It proceeds to
	 * call all the registered appenders in this category and also higher in the
	 * hierarchy depending on the value of the additivity flag.
	 * 
	 * <p>
	 * <b>WARNING</b> Note that passing a {@link Throwable} to this method will
	 * print the name of the <code>Throwable</code> but no stack trace. To print
	 * a stack trace use the {@link #error(Object, Throwable)} form instead.
	 * 
	 * @param message
	 *            the message object to log
	 */
	public void error(Object msg) {
		logger.error(msg);
	}

	/**
	 * Log a message object with the <code>ERROR</code> level including the
	 * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
	 * 
	 * <p>
	 * See {@link #error(Object)} form for more detailed information.
	 * 
	 * @param message
	 *            the message object to log.
	 * @param t
	 *            the exception to log, including its stack trace.
	 */
	public void error(Object msg, Throwable exception) {
		logger.error(msg, exception);
	}

	/**
	 * Log a message object with the {@link Level#DEBUG DEBUG} level.
	 * 
	 * <p>
	 * This method first checks if this category is <code>DEBUG</code> enabled
	 * by comparing the level of this category with the {@link Level#DEBUG
	 * DEBUG} level. If this category is <code>DEBUG</code> enabled, then it
	 * converts the message object (passed as parameter) to a string by invoking
	 * the appropriate {@link org.apache.log4j.or.ObjectRenderer}. It then
	 * proceeds to call all the registered appenders in this category and also
	 * higher in the hierarchy depending on the value of the additivity flag.
	 * 
	 * <p>
	 * <b>WARNING</b> Note that passing a {@link Throwable} to this method will
	 * print the name of the <code>Throwable</code> but no stack trace. To print
	 * a stack trace use the {@link #debug(Object, Throwable)} form instead.
	 * 
	 * @param message
	 *            the message object to log.
	 */
	public void debug(Object msg) {
		if (logger.isDebugEnabled()) {
			logger.debug(msg);
		}
	}

	/**
	 * Log a message object with the <code>DEBUG</code> level including the
	 * stack trace of the {@link Throwable} <code>t</code> passed as parameter.
	 * 
	 * <p>
	 * See {@link #debug(Object)} form for more detailed information.
	 * 
	 * @param message
	 *            the message object to log.
	 * @param t
	 *            the exception to log, including its stack trace.
	 */
	public void debug(Object msg, Throwable exception) {
		if (logger.isDebugEnabled()) {
			logger.debug(msg, exception);
		}
	}

}
